package com.example.demo.web.redis;

import com.alibaba.fastjson.JSON;
import com.example.demo.bean.Menu;
import com.example.demo.utils.SysUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * spirngCache 简化缓存开发
 * 1 原理
 * CacheAutoConfiguration->RedisCacheConfiguration->自动配置了缓存管理器 RedisCacheManager
 * ->初始化缓冲->每个缓冲决定使用什么配置，->如果 有就用已有的，没有就用默认的
 * ->给容器中放入 RedisCacheConfiguration 即可
 */
@Slf4j
@RestController
@RequestMapping("/rediscache")
public class RedisCacheController {
    /**
     *
     */
    @Autowired
    JdbcTemplate jdbcTemplate;

    /*    @Resource// Error creating bean with name 'redisCacheController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'redisTemplate' is expected to be of type 'org.springframework.data.redis.core.StringRedisTemplate' but was actually of type 'org.springframework.data.redis.core.RedisTemplate'
        StringRedisTemplate redisTemplate;*/

     /*   @Resource// 这样可以
        StringRedisTemplate stringRedisTemplate;*/

    @Autowired
    StringRedisTemplate redisTemplate;


    /**
     * 每一个缓存的数据我们都来指定要放到哪个名字的缓冲|缓冲分区【可以按照业务类型】|可以放入多个区
     * 默认行为
     * 1 key默认自动生成，缓存的名字|::SimpleKey []
     * 2 缓存的vaule,使用java序列化机制
     * 3 默认时间ttl -1
     * 自定义
     * 1 指定缓存key|key 属性指定，
     * 2 指定缓存存活时间|spring.cache.redis.time-to-live
     * 3 数据保存为JSON|修改缓存管理器 配置
     */

    //使用了 缓存前缀，key结果变为了CACHE_getMenu
    //@Cacheable(value = {"cache:menu", "menu"},   key = "'db:menu'") //代表当前方法的结果需要缓存，如果缓存中有，方法不用调用，如果缓存中没有，会调用方法
    @Cacheable(value = {"menu", "db:menu"}, key = "#root.methodName")
    //按照方法名设置缓存key|   //使用了 缓存前缀，key结果变为了CACHE_getMenu
    @RequestMapping("menu")
    public String getMenu() {
        List<Menu> menus = getMenus(0L);
        return JSON.toJSONString(menus);
    }

    /**
     * 删除缓存
     */
    //@CacheEvict(value = {"menu"}, key = "'getMenu'")//只能删除单一key
/**************************/
    //可以删掉多个 缓存
    /*    @Caching(evict = {
                @CacheEvict(value = {"menu"}, key = "'getMenu'"),
                @CacheEvict(value = {"db:menu"}, key = "'getMenu'"),
        })*/

    /**************************/
    //删除该分区下所有数据
    @CacheEvict(value = "menu", allEntries = true)
    @RequestMapping("delcache")
    public String cacheEvit() {
        log.info(SysUtils.getDateSplit_());
        return SysUtils.getDateSplit_();
    }

    private List<Menu> getMenus(long id) {
        log.info("方法被调用了");
        return jdbcTemplate.query("select * from t_menu ", new BeanPropertyRowMapper(Menu.class));
    }

}
